package com.me.mysqladmin.util;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.me.mysqladmin.customize.IgnoreCaseMap;
import com.me.mysqladmin.util.NullUtil;

public class BeanUtil {
	/**
	 * 将JavaBean对象写入到map集合
	 * @param bean 一个JavaBean对象
	 */
	public static Map<String, Object> toMap(Object bean) {
		//封装返回对象
		Map<String, Object> beanMapper = new LinkedHashMap<>();
		// 入参判断
		if(NullUtil.isNull(bean)){
			return beanMapper;
		}
		// 如果传入对象已经为Map，则直接返回
		if(bean instanceof Map<?, ?>){
			Map<?, ?> map = (Map<?, ?>) bean;
			Set<?> keySet = map.keySet();
			for(Object key : keySet){
				if(key instanceof String){
					beanMapper.put((String) key, map.get(key));
				}
			}
			return beanMapper;
		}
		//解析JavaBean
		try {
			//获取所有bean属性(不包括class)的描述器
			PropertyDescriptor[] pds = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
			for(PropertyDescriptor pd : pds){
				String key = pd.getName();	//bean属性名
				Object value = pd.getReadMethod().invoke(bean);//调用get方法，获取返回值
				beanMapper.put(key, value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return beanMapper;
	}
	
	/**
	 * 获取Javanbean的所有属性名称，若传入一个Map，则获取key的集合
	 * @param bean 一个JavaBean对象
	 */
	public static List<String> getProps(Object bean){
		// 封装返回值
		List<String> props = new ArrayList<>();
		// 入参判断
		if(NullUtil.isNull(bean)){
			return props;
		}
		// 如果传入对象已经为Map，则直接返回key的集合
		if(bean instanceof Map<?, ?>){
			Map<?, ?> map = (Map<?, ?>) bean;
			Set<?> keySet = map.keySet();
			for(Object key : keySet){
				if(key instanceof String){
					props.add((String) key);
				}
			}
			return props;
		}
		// 解析JavaBean
		try {
			//获取所有bean属性(不包括class属性)的描述器
			PropertyDescriptor[] pds = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
			for(PropertyDescriptor pd : pds){
				props.add(pd.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return props;
	}
	
	/**
	 * 通过匹配map中的key和对象中的属性，将map集合写入到指定类型的JavaBean对象
	 * @param beanMapper	待写入的map集合
	 * @param acceptType	'接收'值对象，以Bean类型来接收
	 */
	public static <T> T toBean(Map<String, Object> beanMapper, Class<T> acceptType) {
		//封装返回对象
		T bean = getInstance(acceptType);
		// 方法入参校验
		if(NullUtil.isEmpty(beanMapper)){
			return bean;
		}
		//解析beanMapper
		try {
			//获取所有bean属性(不包括class)的描述器
			PropertyDescriptor[] pds = Introspector.getBeanInfo(acceptType, Object.class).getPropertyDescriptors();
			//遍历所有bean属性，当map中没有当前bean属性时，会自动跳过
			for(PropertyDescriptor pd : pds){
				String prop = pd.getName();	//bean属性名
				//将map转成忽略key大小写的map，如果map中存在该属性，就将属性值写入对象中
				if(toIgnoreCaseMap(beanMapper).containsKey(prop)){
					Object value = beanMapper.get(prop);	//获取属性值，用Object来接收，实际指向具体的类型
					pd.getWriteMethod().invoke(bean, value);//调用set方法
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bean;
	}
	
	/**
	 * 通过匹配map中的key和对象中的属性，将多个map集合写入到多个指定类型的JavaBean对象
	 * @param mapList		待写入的map集合的集合
	 * @param acceptType	'接收'值对象，以Bean类型来接收
	 * @return				返回JavaBean对象的集合
	 */
	public static <T> List<T> toBeanList(List<Map<String, Object>> mapList, Class<T> acceptType) {
		// 方法入参校验
		if(NullUtil.isEmpty(mapList)){
			return Collections.emptyList();
		}
		// 封装返回对象
		List<T> beanList = new ArrayList<T>();
		// 遍历mapList
		for (Map<String, Object> map : mapList) {
			beanList.add(toBean(map, acceptType));
		}
		return beanList;
	}
	
	/**
	 * 判断一个JavaBean是否包含指定的Bean属性（忽略大小写）
	 * @param bean 一个JavaBean对象
	 * @param prop Bean属性名
	 */
	public static boolean containsProp(Object bean, String prop) {
		return containsProp(bean.getClass(), prop);
	}
	
	/**
	 * 判断一个JavaBean是否包含指定的Bean属性（忽略大小写）
	 * @param type 一个JavaBean类型
	 * @param prop Bean属性名
	 */
	public static <T> boolean containsProp(Class<T> type, String prop) {
		// 方法入参校验
		if(NullUtil.isNull(type) || NullUtil.isNull(prop)){
			return false;
		}
		//解析JavaBean
		try {
			PropertyDescriptor[] pds = Introspector.getBeanInfo(type).getPropertyDescriptors();
			for(PropertyDescriptor pd : pds){
				if(prop.equalsIgnoreCase(pd.getName())){
					return true;
				}
			}
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 将普通的Map集合转成忽略key值大小写的Map集合
	 */
	private static Map<String, Object> toIgnoreCaseMap(Map<String, Object> map){
		// 方法入参校验
		if(NullUtil.isEmpty(map)){
			return new IgnoreCaseMap<>();
		}
		//如果该map的实现类已经是IgnoreCaseMap，则直接返回
		if(map instanceof IgnoreCaseMap){
			return map;
		}
		//暂存结果
		Map<String, Object> temp = new IgnoreCaseMap<Object>();
		//遍历参数map
		Set<String> keySet = map.keySet();
		for(String key : keySet){
			temp.put(key, map.get(key));
		}
		//返回结果
		return map=temp;
	}
	
	/**
	 * 根据元类实例化类，返回类的实例
	 */
	public static <T> T getInstance(Class<T> type) {
		T t = null;
		try {
			t = type.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return t;
	}
}
